package org.altervista.cp.microkernel.install.sql;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import org.altervista.cp.microkernel.log.Log;

public final class SQLScriptExcecutor {

	private static final Log log = new Log(SQLScriptExcecutor.class);

	public static void execute(String scriptPath, DataSource ds)
			throws SQLException, IOException {
		execute(new File(scriptPath), ds);
	}

	public static void execute(String scriptPath, Connection c)
			throws SQLException, IOException {
		execute(new File(scriptPath), c);
	}

	public static void execute(File scriptFile, DataSource ds)
			throws SQLException, IOException {
		Connection c = null;
		try {
			c = ds.getConnection();
			execute(scriptFile, c);
		} finally {
			if (c != null) {
				c.close();
			}
		}
	}

	public static void execute(File scriptFile, Connection c)
			throws SQLException, IOException {
		log.info("Start executing SQL script: {0}", scriptFile);
		boolean autocommit = false;
		try {
			autocommit = c.getAutoCommit();
			if (autocommit) {
				c.setAutoCommit(false);
			}

			StringBuffer sbSQL = new StringBuffer();
			BufferedReader br = new BufferedReader(new FileReader(scriptFile));
			String line = null;
			while ((line = br.readLine()) != null) {
				sbSQL.append(line);
				if (line.endsWith(";")) {
					int len = sbSQL.length();
					sbSQL.deleteCharAt(len - 1);
					log.info("Executing SQL statement: {0}", sbSQL);
					Statement stm = c.createStatement();
					String sql = sbSQL.toString().trim();
					try {
						stm.execute(sql);
					} catch (SQLException e) {
						log.error("", e);
						if (sql.toLowerCase().startsWith("drop ")) {
							log
									.info(
											"Skipped DROP of a non existing entity ({0})",
											sql);
						} else {
							throw e;
						}
					}
					log.info("SQL statement executed successfully");
					stm.close();
					sbSQL.delete(0, len);
				} else {
					sbSQL.append("\n");
				}
			}
			br.close();

			c.commit();
			log.info("End executing SQL script: {0}", scriptFile);
		} finally {
			c.rollback();
			if (autocommit) {
				c.setAutoCommit(true);
			}
		}
	}
}
